import json
import time

from django.http import JsonResponse
from django.shortcuts import render
from django.views import View
from django.core.paginator import Paginator, EmptyPage
from django.db.models import F
from datetime import datetime

from django_redis import get_redis_connection

from apps.app.models import User
from apps.goods.models import ContentCategory, GoodsCategory, SKU, SPUSpecification, GoodsVisitCount, BrowseHistory
from django.forms import model_to_dict
from django.db.models.query import QuerySet

from apps.goods.utils import get_breadcrumb
from md_sc.config import QINIU_DOMAIN, REDIS_KEY_MAP


# Create your views here.

class IndexView(View):
    def get(self, request):
        """提供首页广告界面"""

        # 广告数据
        contents = {}
        content_categories = ContentCategory.objects.all()
        for cat in content_categories:
            # contents[cat.key] = self.qiniu_model_to_dict(cat.contents.filter(status=True).order_by('sequence'))
            contents[cat.key] = cat.contents.filter(status=True).order_by('sequence')
        # 渲染模板的上下文
        context = {
            'categories': [model_to_dict(categori) for categori in content_categories],
            'contents': contents,
        }
        return render(request, 'index.html', context)


class Goods(View):
    def get(self, request, category_id):
        category = GoodsCategory.objects.filter(id=category_id).first()
        page = int(request.GET.get('page', 0))
        page_size = int(request.GET.get('page_size', 5))
        order = request.GET.get('ordering', 'id').replace('create_time', 'id')

        skus = []
        skus_data = Paginator(SKU.objects.filter(category=category, is_launched=True).order_by(order),
                              page_size)
        for sku in skus_data.page(page):
            skus.append({
                "id": sku.id,
                "default_image_url": str(sku.default_image),
                "name": sku.name,
                "url2": f"/detail/{sku.id}/",
                "price": str(sku.price)
            })

        return JsonResponse({
            "code": 0,
            "errmsg": "ok",
            "breadcrumb": get_breadcrumb(category),
            "list": skus,
            "count": skus_data.num_pages  # 分页总数
        })


class Hot(View):
    def get(self, request, category_id):
        return JsonResponse({
            "code": 0,
            "errmsg": "ok",
            "hot_skus": self.get_hot(category_id),
        })

    @staticmethod
    def get_hot(category_id):
        hot_skus = []
        skus_data = SKU.objects.filter(category_id=category_id, is_launched=True).order_by('-sales')[:2]
        for sku in skus_data:
            hot_skus.append({
                "id": sku.id,
                "default_image_url": str(sku.default_image),
                "name": sku.name,
                "price": str(sku.price)
            })
        return hot_skus


class SKUView(View):
    my_cache_map = {}

    @staticmethod
    def my_cache(f):

        def inner(*args, **kwargs):
            sku_id = kwargs.get('sku_id')
            if sku_id in SKUView.my_cache_map:
                return SKUView.my_cache_map.get(sku_id)
            ret = f(*args, **kwargs)
            SKUView.my_cache_map[sku_id] = ret
            return ret

        return inner

    @my_cache
    def get(self, request, sku_id):
        sku_data = SKU.objects.filter(id=sku_id).first()
        breadcrumb = get_breadcrumb(sku_data.category)

        content_categories = ContentCategory.objects.all()
        context = {
            'categories': [model_to_dict(categori) for categori in content_categories],
            'breadcrumb': breadcrumb,
            'sku': sku_data,
            'hot_skus': Hot.get_hot(sku_data.category_id),
            'specs': self.get_goods_specs(sku_data)

        }

        LookHistory.toos(request, sku_id)
        return render(request, 'detail.html', context)

    def get_goods_specs(self, sku):
        # 构建当前商品的规格键
        sku_specs = sku.specs.order_by('spec_id')
        sku_key = []
        for spec in sku_specs:
            sku_key.append(spec.option.id)

        # 获取当前商品的所有SKU
        skus = sku.spu.skus.all()
        # 构建不同规格参数（选项）的sku字典
        spec_sku_map = {}
        for s in skus:
            # 获取sku的规格参数
            s_specs = s.specs.order_by('spec_id')
            # 用于形成规格参数-sku字典的键
            key = []
            for spec in s_specs:
                key.append(spec.option.id)
            # 向规格参数-sku字典添加记录
            spec_sku_map[tuple(key)] = s.id

        # 以下代码为：在每个选项上绑定对应的sku_id值
        # 获取当前商品的规格信息
        goods_specs = sku.spu.specs.order_by('id')
        # 若当前sku的规格信息不完整，则不再继续
        if len(sku_key) < len(goods_specs):
            return
        for index, spec in enumerate(goods_specs):
            # 复制当前sku的规格键
            key = sku_key[:]
            # 该规格的选项
            spec_options = spec.options.all()
            for option in spec_options:
                # 在规格参数sku字典中查找符合当前规格的sku
                key[index] = option.id
                option.sku_id = spec_sku_map.get(tuple(key))
            spec.spec_options = spec_options

        return goods_specs


class VisitCount(View):
    def post(self, request, category_id):
        goodcate = GoodsCategory.objects.filter(id=category_id).first()
        today = datetime.today()
        visit = goodcate.visit.filter(date=today).first()

        if not visit:
            visit = GoodsVisitCount.objects.create(category_id=category_id)

        visit.count = F('count') + 1

        # visit.count += 1
        visit.save()
        return JsonResponse({'code': 0, 'errmsg': 'OK'})


class LookHistory(View):

    @classmethod
    def toos(cls, request, sku_id):
        return cls().post(request, sku_id)

    def post(self, request, sku_id=None):
        request.user = User.objects.filter(id=11).first()
        if not sku_id:
            data = json.loads(request.body.decode())
            sku_id = data.get('sku_id')
        histories = request.user.history.all()

        for history in histories:
            if history.sku_id == sku_id:
                history.time_s = int(time.time())
                history.save()
                break
        else:

            BrowseHistory.objects.create(time_s=int(time.time()),
                                         user_id=request.user.id,
                                         sku_id=sku_id)
            if len(histories) >= 6:
                for i in list(request.user.history.all())[:-5]:
                    i.delete()

        histories = request.user.history.all()
        redis_coon = get_redis_connection('history')
        key = REDIS_KEY_MAP.get('History') + str(request.user.id)
        redis_data = {json.dumps({
            'id': i.sku.id,
            'name': i.sku.name,
            'default_image_url': str(i.sku.default_image),
            'price': str(i.sku.price),
        }): i.time_s for i in histories}

        redis_coon.zadd(name=key, mapping=redis_data)
        return JsonResponse({
            "code": "0",
            "errmsg": "OK",
        })

    def get(self, request):
        uid = request.user.id
        redis_coon = get_redis_connection('history')
        sku_data = redis_coon.zrange(REDIS_KEY_MAP.get('History') + str(uid), 0, -1)

        if not sku_data:
            history = BrowseHistory.objects.filter(user=request.user).all()
            skus = [{
                'id': i.sku.id,
                'name': i.sku.name,
                'default_image_url': str(i.sku.default_image),
                'price': i.sku.price,
            } for i in history]
        else:
            skus = [json.loads(sku.decode()) for sku in sku_data]
        return JsonResponse({
            "code": "0",
            "errmsg": "OK",
            "skus": skus
        })
